#include "visitordata.h"
#include "../templates/hstringlist.h"
#include "../core/nodes/classtype.h"

ClassSemantic * SemanticVisitorData::getClassByName(const std::string & name)
{
	if (m_classes.find(name)!=m_classes.end()) {
		return m_classes[name];
	}
	else {
		if (m_libraryclasses.find(name)!=m_libraryclasses.end()) {
			return m_libraryclasses[name];
		}
		else {
				//If this is ARRAY[T], try to generate 
			    hst::string str=name.c_str();
				hst::string arrayname="ARRAY";
				if (str.length()>arrayname.length()) 
				{
					//If this is array[T]
					if (str.subString(0,arrayname.length())==arrayname && str[arrayname.length()]=='[')
					{

						hst::string t=str.data()+arrayname.length()+1;
						t.remove(t.length()-1);
						//If T exists,creates
						ClassSemantic * get=getClassByName(std::string(t.data()));
						if (get) {
							createArrayType(t.data());
							return m_libraryclasses[name];
						}

					}
				}
		}
	}
	return NULL;
}

ClassSemantic * SemanticVisitorData::getClassByName(ClassTypeNode * node)
{
	if (m_classes.find(node->fullName())!=m_classes.end()) {
		return m_classes[node->fullName()];
	}
	else {
		if (m_libraryclasses.find(node->fullName())!=m_libraryclasses.end()) {
			return m_libraryclasses[node->fullName()];
		}
		else {
			if (node->partialName()=="ARRAY" && node->isTAAmount(1)) {
				if (getClassByName(node->getTA(0))) {
					createArrayType(node->getTA(0));
					return m_libraryclasses[node->fullName()];
				}
			}
		}
	}
	return NULL;
}

void SemanticVisitorData::checkAndMarkRootClassProcedure()
{
 ClassSemantic * _class=getClassByName(m_rootclass);
 if (_class)
 {
	 if (_class->cnode()->type()==CLM_DEFERRED)
	 {
		 add(new AbstractRoot(_class->cnode()));
	 }
	 Method * _proc=_class->getMethodByName(m_rootproc);
	 if (_proc)
	 {
		 std::vector<std::string> args;
		 if (_proc->methodType() & FDT_ABSTRACT)
		 {
			 add(new AbstractRootProcedure(_proc->declarationPlace()));
		 }
		 if (_proc->hasFormalArgSignature(args,m_rootclass))
		 {
			 _class->markAsRoot();
			 _proc->markAsRoot();
		 }
		 else
		 {
			 args.push_back("ARRAY[STRING]");
			 if (_proc->hasFormalArgSignature(args,m_rootclass))
			 {
			  _class->markAsRoot();
			  _proc->markAsRoot();
		     }
			 else
			 {
				 add(new RootMethodHasIncorrectSignature(_class->cnode(),m_rootproc));
			 }
		 }
	 }
	 else add(new RootMethodDoesNotExists(_class->cnode(),m_rootproc));
 }
 else add(new RootClassDoesNotExists(m_rootclass));
}


bool SemanticVisitorData::isAncestor(const std::string & possible_ancestor,const std::string & me,InheritanceSemantic * excluded)
{
	ClassSemantic * sem=getClassByName(me);
	if (!sem)
		return false;
	for (unsigned int i=0;i<sem->semanticInheritCount();i++)
	{
		std::string curancestor=sem->semanticInherit(i);
		if (sem->isEqualInheritance(i,excluded)==false) {
		if (curancestor==possible_ancestor)
			return true;
		if (isAncestor(possible_ancestor,curancestor))
			return true;
		}
	}
	return false;
}


bool SemanticVisitorData::isDerived(const std::string & posssible_derived, const std::string & me)
{
	return isAncestor(me,posssible_derived);
}